package server

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	l "house-src/basic/init"
	__ "house-src/basic/proto"
	"house-src/handler/models"
	"house-src/untils"
	"log"
	"math/rand"
	"strconv"
	"time"
)

// 添加预约
func (s *Server) AddReservation(_ context.Context, in *__.AddReservationReq) (*__.AddReservationResp, error) {
	var err error

	var customer models.Customer
	if err = customer.GetCustomerById(int(in.CustomerId)); err != nil {
		return nil, errors.New("客户查询失败")
	}

	if customer.ID == 0 {
		return nil, errors.New("请前往登录")
	}

	var cleaner models.Cleaner
	if err = cleaner.GetCleanerById(int(in.CleanerId)); err != nil {
		return nil, errors.New("清洁师查询失败")
	}

	if cleaner.Status != 1 {
		return nil, errors.New("没有空闲的清洁师")
	}

	//cleanerId := cleaner.GetFreeCleaner()
	//
	//if cleanerId == 0 {
	//	return nil, errors.New("没有清洁师接单")
	//}

	start, err := time.Parse(time.DateTime, in.StartTime)
	if err != nil {
		return nil, errors.New("预约时间格式错误")
	}

	//添加分布式锁
	if !untils.LockCleaner(in.CleanerId) {
		return nil, errors.New("该订单已被其他清洁师抢单")
	}

	//计算难度系数
	difficulty := untils.CountDifficulty(in.Address, int(in.Area))

	//计算价格
	price := untils.CountOrder(in.ClassType, int(in.Area), float64(in.Duration))

	//添加预约
	var reservation models.Reservation
	reservation = models.Reservation{
		CustomerId: int(in.CustomerId),
		CleanerId:  int(in.CleanerId),
		Title:      in.ClassType,
		Price:      price,
		Address:    in.Address,
		Area:       int(in.Area),
		Difficulty: difficulty,
		StartTime:  &start,
		Duration:   float64(in.Duration),
		Status:     1, //未开始
	}
	if err = reservation.AddReservation(); err != nil {
		return nil, errors.New("预约添加失败")
	}

	//订单编号
	t := time.Now().Unix()
	code := int64(rand.Intn(10))
	orderSn := t + in.CustomerId + code

	//生成订单
	var order models.Order
	order = models.Order{
		CustomerId:    int(in.CustomerId),
		CleanerId:     int(in.CleanerId),
		ReservationId: int(reservation.ID),
		OrderSn:       strconv.FormatInt(orderSn, 10),
		OrderPrice:    price,
		Status:        1, //待接单
		PayMothed:     1,
		PayStatus:     1, //待支付
	}

	//存入mq中 生产者
	mq := l.NewRabbitMQSimple("" + "2301ahouses")
	marshal, _ := json.Marshal(order)
	mq.PublishSimple(marshal)

	//es同步
	var es untils.ES
	es.Id = strconv.Itoa(int(order.ID))
	es.Index = "houses"
	es.Body = order
	_ = es.SyncEs()

	//更新订单状态
	order.Status = 2 //已接单
	if err = order.UpdateStatus(int(order.ID)); err != nil {
		return nil, errors.New("更新订单状态失败")
	}

	return &__.AddReservationResp{
		ReservationId: int64(reservation.ID),
	}, nil
}

// 创建订单
func (s *Server) AddOrder(_ context.Context, in *__.AddOrderReq) (*__.AddOrderResp, error) {
	var err error

	var order models.Order

	mq := l.NewRabbitMQSimple("" + "2301ahouses")
	msgs, _ := mq.ConsumeSimple()

	forever := make(chan bool)
	//启用协程处理消息
	go func() {
		for d := range msgs {
			//消息逻辑处理，可以自行设计逻辑
			log.Printf("Received a message: %s", d.Body)

			_ = json.Unmarshal(d.Body, &order)

			if err = order.AddOrder(); err != nil {
				log.Fatal("订单创建失败", err)
				return
			}

		}
	}()

	log.Printf(" [*] Waiting for messages. To exit press CTRL+C")
	<-forever

	return &__.AddOrderResp{
		OrderSn: order.OrderSn,
		Status:  int64(order.Status),
	}, nil
}

// 拒单
func (s *Server) RejectOrder(_ context.Context, in *__.RejectOrderReq) (*__.RejectOrderResp, error) {
	var err error

	var cleaner models.Cleaner
	if err = cleaner.GetCleanerById(int(in.CleanerId)); err != nil {
		return nil, errors.New("清洁师查询失败")
	}

	if cleaner.ID == 0 {
		return nil, errors.New("请前往登录")
	}

	var order models.Order
	if err = order.GetOrderById(int(in.OrderId)); err != nil {
		{
			return nil, errors.New("订单查询失败")
		}
	}

	if order.ID == 0 {
		return nil, errors.New("该订单不存在")
	}

	if err = cleaner.GetCleanerById(order.CleanerId); err != nil {
		return nil, errors.New("清洁师查询失败")
	}

	if cleaner.ID != uint(in.CleanerId) {
		return nil, errors.New("该订单不是您的")
	}

	//更新订单信息
	order.Status = 1 //待接单
	if err = order.UpdateStatus(int(in.OrderId)); err != nil {
		return nil, errors.New("拒单失败")
	}

	//更新清洁师接单状态
	cleaner.Status = 1 //空闲中
	if err = cleaner.UpdateStatus(int(in.CleanerId)); err != nil {
		return nil, errors.New("清洁师接单状态更新失败")
	}

	return &__.RejectOrderResp{}, nil
}

// 确认客户
func (s *Server) ConfirmCustomer(_ context.Context, in *__.ConfirmCustomerReq) (*__.ConfirmCustomerResp, error) {
	var err error

	var cleaner models.Cleaner
	if err = cleaner.GetCleanerById(int(in.CleanerId)); err != nil {
		return nil, errors.New("清洁师查询失败")
	}

	if cleaner.ID == 0 {
		return nil, errors.New("请前往登录")
	}

	var order models.Order
	if err = order.GetOrderById(int(in.OrderId)); err != nil {
		{
			return nil, errors.New("订单查询失败")
		}
	}

	if order.ID == 0 {
		return nil, errors.New("该订单不存在")
	}

	if err = cleaner.GetCleanerById(order.CleanerId); err != nil {
		return nil, errors.New("清洁师查询失败")
	}

	if cleaner.ID != uint(in.CleanerId) {
		return nil, errors.New("该订单不是您的")
	}

	//确认客户
	var customer models.Customer
	if err = customer.GetCustomerById(order.CustomerId); err != nil {
		return nil, errors.New("客户查询失败")
	}

	if customer.Mobile[7:11] != in.Mobile {
		return nil, errors.New("客户确认失败")
	}

	//更新订单信息
	order.Status = 2 //已接单
	if err = order.UpdateStatus(int(in.OrderId)); err != nil {
		return nil, errors.New("接单失败")
	}

	//更新清洁师接单状态
	cleaner.Status = 2 //忙碌中
	if err = cleaner.UpdateStatus(int(in.CleanerId)); err != nil {
		return nil, errors.New("清洁师接单状态更新失败")
	}

	return &__.ConfirmCustomerResp{
		OrderId: int64(order.ID),
	}, nil
}

// 结束服务
func (s *Server) EndOrder(_ context.Context, in *__.EndOrderReq) (*__.EndOrderResp, error) {
	var err error

	var cleaner models.Cleaner
	if err = cleaner.GetCleanerById(int(in.CleanerId)); err != nil {
		return nil, errors.New("清洁师查询失败")
	}

	if cleaner.ID == 0 {
		return nil, errors.New("请前往登录")
	}

	var order models.Order
	if err = order.GetOrderById(int(in.OrderId)); err != nil {
		{
			return nil, errors.New("订单查询失败")
		}
	}

	if order.ID == 0 {
		return nil, errors.New("该订单不存在")
	}

	if err = cleaner.GetCleanerById(order.CleanerId); err != nil {
		return nil, errors.New("清洁师查询失败")
	}

	if cleaner.ID != uint(in.CleanerId) {
		return nil, errors.New("该订单不是您的")
	}

	//更新订单信息
	order.Status = 3 //已结束
	if err = order.UpdateStatus(int(in.OrderId)); err != nil {
		return nil, errors.New("接单失败")
	}

	//更新清洁师接单状态
	cleaner.Status = 1 //空闲中
	if err = cleaner.UpdateStatus(int(in.CleanerId)); err != nil {
		return nil, errors.New("清洁师接单状态更新失败")
	}

	//生成支付链接
	pay := untils.ALiPay{}
	url := pay.AlipayOrder(order.OrderSn, fmt.Sprintf("%.2f", order.OrderPrice))

	return &__.EndOrderResp{
		OrderSn: order.OrderSn,
		PayUrl:  url,
	}, nil
}

// 更新支付状态
func (s *Server) UpdatePayStatus(_ context.Context, in *__.UpdatePayStatusReq) (*__.UpdatePayStatusResp, error) {
	var err error

	var order models.Order
	if err = order.GetOrderInfo(in.OrderSn); err != nil {
		return nil, errors.New("订单查询失败")
	}

	if order.ID == 0 {
		return nil, errors.New("该订单不存在")
	}

	order.PayStatus = int(in.Status)
	if err = order.UpdatePayStatus(in.OrderSn, int(in.Status)); err != nil {
		return nil, errors.New("订单支付状态更新失败")
	}

	return &__.UpdatePayStatusResp{}, nil
}

// 订单列表
func (s *Server) GetOrderList(_ context.Context, in *__.GetOrderListReq) (*__.GetOrderListResp, error) {

	var order models.Order
	list, _ := order.GetOrderList(int(in.CustomerId), int(in.Status))

	var orderList []*__.GetOrderInfo
	for _, o := range list {
		orderList = append(orderList, &__.GetOrderInfo{
			CustomerId: int64(o.CustomerId),
			CleanerId:  int64(o.CleanerId),
			OrderSn:    o.OrderSn,
			OrderPrice: float32(o.OrderPrice),
			Status:     int64(o.Status),
			PayMothed:  int64(o.PayMothed),
			PayStatus:  int64(o.PayStatus),
		})
	}

	return &__.GetOrderListResp{
		OrderList: orderList,
	}, nil
}

// 订单详情
func (s *Server) GetOrderDetail(_ context.Context, in *__.GetOrderDetailReq) (*__.GetOrderDetailResp, error) {
	var err error

	var order models.Order
	if err = order.GetOrderById(int(in.OrderId)); err != nil {
		return nil, errors.New("订单查询失败")
	}

	if order.ID == 0 {
		return nil, errors.New("该订单不存在")
	}

	var cleaner models.Cleaner
	if err = cleaner.GetCleanerById(order.CleanerId); err != nil {
		return nil, errors.New("清洁师查询失败")
	}

	var reservation models.Reservation
	if err = reservation.GetReservation(order.ReservationId); err != nil {
		return nil, errors.New("预约查询失败")
	}

	t := fmt.Sprintf("%v", reservation.StartTime)

	return &__.GetOrderDetailResp{
		CustomerId: int64(order.CustomerId),
		OrderSn:    order.OrderSn,
		OrderPrice: float32(order.OrderPrice),
		Status:     int64(order.Status),
		PayMothed:  int64(order.PayMothed),
		PayStatus:  int64(order.PayStatus),
		RealName:   cleaner.RealName,
		Desc:       cleaner.Desc,
		Address:    reservation.Address,
		ClassType:  cleaner.ClassType,
		Image:      cleaner.Image,
		Area:       int64(reservation.Area),
		Difficulty: float32(reservation.Difficulty),
		StartTime:  t,
		Duration:   float32(reservation.Duration),
	}, nil
}
